/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package controller;

import controller.exceptions.NonexistentEntityException;
import controller.exceptions.PreexistingEntityException;
import controller.exceptions.RollbackFailureException;
import java.io.Serializable;
import java.sql.ResultSet;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import model.entity.Favorite;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.transaction.UserTransaction;
import model.entity.Caterer;
import model.entity.Restaurant;

/**
 *
 * @author lnngu_000
 */
public class CatererJpaController implements Serializable {

    public CatererJpaController(EntityManagerFactory emf) {
        this.emf = emf;
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Caterer caterer) throws PreexistingEntityException, RollbackFailureException, Exception {
        if (caterer.getFavoriteCollection() == null) {
            caterer.setFavoriteCollection(new ArrayList<Favorite>());
        }
        if (caterer.getRestaurantCollection() == null) {
            caterer.setRestaurantCollection(new ArrayList<Restaurant>());
        }
        EntityManager em = null;
        try {

            em = getEntityManager();
            em.getTransaction().begin();
            Collection<Favorite> attachedFavoriteCollection = new ArrayList<Favorite>();
            for (Favorite favoriteCollectionFavoriteToAttach : caterer.getFavoriteCollection()) {
                favoriteCollectionFavoriteToAttach = em.getReference(favoriteCollectionFavoriteToAttach.getClass(), favoriteCollectionFavoriteToAttach.getFavoriteId());
                attachedFavoriteCollection.add(favoriteCollectionFavoriteToAttach);
            }
            caterer.setFavoriteCollection(attachedFavoriteCollection);
            Collection<Restaurant> attachedRestaurantCollection = new ArrayList<Restaurant>();
            for (Restaurant restaurantCollectionRestaurantToAttach : caterer.getRestaurantCollection()) {
                restaurantCollectionRestaurantToAttach = em.getReference(restaurantCollectionRestaurantToAttach.getClass(), restaurantCollectionRestaurantToAttach.getRestaurantId());
                attachedRestaurantCollection.add(restaurantCollectionRestaurantToAttach);
            }
            caterer.setRestaurantCollection(attachedRestaurantCollection);
            em.persist(caterer);
            for (Favorite favoriteCollectionFavorite : caterer.getFavoriteCollection()) {
                Caterer oldCatererIdOfFavoriteCollectionFavorite = favoriteCollectionFavorite.getCatererId();
                favoriteCollectionFavorite.setCatererId(caterer);
                favoriteCollectionFavorite = em.merge(favoriteCollectionFavorite);
                if (oldCatererIdOfFavoriteCollectionFavorite != null) {
                    oldCatererIdOfFavoriteCollectionFavorite.getFavoriteCollection().remove(favoriteCollectionFavorite);
                    oldCatererIdOfFavoriteCollectionFavorite = em.merge(oldCatererIdOfFavoriteCollectionFavorite);
                }
            }
            for (Restaurant restaurantCollectionRestaurant : caterer.getRestaurantCollection()) {
                Caterer oldCatererIdOfRestaurantCollectionRestaurant = restaurantCollectionRestaurant.getCatererId();
                restaurantCollectionRestaurant.setCatererId(caterer);
                restaurantCollectionRestaurant = em.merge(restaurantCollectionRestaurant);
                if (oldCatererIdOfRestaurantCollectionRestaurant != null) {
                    oldCatererIdOfRestaurantCollectionRestaurant.getRestaurantCollection().remove(restaurantCollectionRestaurant);
                    oldCatererIdOfRestaurantCollectionRestaurant = em.merge(oldCatererIdOfRestaurantCollectionRestaurant);
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            try {
            } catch (Exception re) {
                throw new RollbackFailureException("An error occurred attempting to roll back the transaction.", re);
            }
            if (findCaterer(caterer.getCatererId()) != null) {
                throw new PreexistingEntityException("Caterer " + caterer + " already exists.", ex);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Caterer caterer) throws NonexistentEntityException, RollbackFailureException, Exception {
        EntityManager em = null;
        try {

            em = getEntityManager();
            em.getTransaction().begin();
            Caterer persistentCaterer = em.find(Caterer.class, caterer.getCatererId());
            Collection<Favorite> favoriteCollectionOld = persistentCaterer.getFavoriteCollection();
            Collection<Favorite> favoriteCollectionNew = caterer.getFavoriteCollection();
            Collection<Restaurant> restaurantCollectionOld = persistentCaterer.getRestaurantCollection();
            Collection<Restaurant> restaurantCollectionNew = caterer.getRestaurantCollection();
            Collection<Favorite> attachedFavoriteCollectionNew = new ArrayList<Favorite>();
            for (Favorite favoriteCollectionNewFavoriteToAttach : favoriteCollectionNew) {
                favoriteCollectionNewFavoriteToAttach = em.getReference(favoriteCollectionNewFavoriteToAttach.getClass(), favoriteCollectionNewFavoriteToAttach.getFavoriteId());
                attachedFavoriteCollectionNew.add(favoriteCollectionNewFavoriteToAttach);
            }
            favoriteCollectionNew = attachedFavoriteCollectionNew;
            caterer.setFavoriteCollection(favoriteCollectionNew);
            Collection<Restaurant> attachedRestaurantCollectionNew = new ArrayList<Restaurant>();
            for (Restaurant restaurantCollectionNewRestaurantToAttach : restaurantCollectionNew) {
                restaurantCollectionNewRestaurantToAttach = em.getReference(restaurantCollectionNewRestaurantToAttach.getClass(), restaurantCollectionNewRestaurantToAttach.getRestaurantId());
                attachedRestaurantCollectionNew.add(restaurantCollectionNewRestaurantToAttach);
            }
            restaurantCollectionNew = attachedRestaurantCollectionNew;
            caterer.setRestaurantCollection(restaurantCollectionNew);
            caterer = em.merge(caterer);
            for (Favorite favoriteCollectionOldFavorite : favoriteCollectionOld) {
                if (!favoriteCollectionNew.contains(favoriteCollectionOldFavorite)) {
                    favoriteCollectionOldFavorite.setCatererId(null);
                    favoriteCollectionOldFavorite = em.merge(favoriteCollectionOldFavorite);
                }
            }
            for (Favorite favoriteCollectionNewFavorite : favoriteCollectionNew) {
                if (!favoriteCollectionOld.contains(favoriteCollectionNewFavorite)) {
                    Caterer oldCatererIdOfFavoriteCollectionNewFavorite = favoriteCollectionNewFavorite.getCatererId();
                    favoriteCollectionNewFavorite.setCatererId(caterer);
                    favoriteCollectionNewFavorite = em.merge(favoriteCollectionNewFavorite);
                    if (oldCatererIdOfFavoriteCollectionNewFavorite != null && !oldCatererIdOfFavoriteCollectionNewFavorite.equals(caterer)) {
                        oldCatererIdOfFavoriteCollectionNewFavorite.getFavoriteCollection().remove(favoriteCollectionNewFavorite);
                        oldCatererIdOfFavoriteCollectionNewFavorite = em.merge(oldCatererIdOfFavoriteCollectionNewFavorite);
                    }
                }
            }
            for (Restaurant restaurantCollectionOldRestaurant : restaurantCollectionOld) {
                if (!restaurantCollectionNew.contains(restaurantCollectionOldRestaurant)) {
                    restaurantCollectionOldRestaurant.setCatererId(null);
                    restaurantCollectionOldRestaurant = em.merge(restaurantCollectionOldRestaurant);
                }
            }
            for (Restaurant restaurantCollectionNewRestaurant : restaurantCollectionNew) {
                if (!restaurantCollectionOld.contains(restaurantCollectionNewRestaurant)) {
                    Caterer oldCatererIdOfRestaurantCollectionNewRestaurant = restaurantCollectionNewRestaurant.getCatererId();
                    restaurantCollectionNewRestaurant.setCatererId(caterer);
                    restaurantCollectionNewRestaurant = em.merge(restaurantCollectionNewRestaurant);
                    if (oldCatererIdOfRestaurantCollectionNewRestaurant != null && !oldCatererIdOfRestaurantCollectionNewRestaurant.equals(caterer)) {
                        oldCatererIdOfRestaurantCollectionNewRestaurant.getRestaurantCollection().remove(restaurantCollectionNewRestaurant);
                        oldCatererIdOfRestaurantCollectionNewRestaurant = em.merge(oldCatererIdOfRestaurantCollectionNewRestaurant);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            try {
            } catch (Exception re) {
                throw new RollbackFailureException("An error occurred attempting to roll back the transaction.", re);
            }
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Integer id = caterer.getCatererId();
                if (findCaterer(id) == null) {
                    throw new NonexistentEntityException("The caterer with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(Integer id) throws NonexistentEntityException, RollbackFailureException, Exception {
        EntityManager em = null;
        try {

            em = getEntityManager();
            Caterer caterer;
            em.getTransaction().begin();
            try {
                caterer = em.getReference(Caterer.class, id);
                caterer.getCatererId();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The caterer with id " + id + " no longer exists.", enfe);
            }
            Collection<Favorite> favoriteCollection = caterer.getFavoriteCollection();
            for (Favorite favoriteCollectionFavorite : favoriteCollection) {
                favoriteCollectionFavorite.setCatererId(null);
                favoriteCollectionFavorite = em.merge(favoriteCollectionFavorite);
            }
            Collection<Restaurant> restaurantCollection = caterer.getRestaurantCollection();
            for (Restaurant restaurantCollectionRestaurant : restaurantCollection) {
                restaurantCollectionRestaurant.setCatererId(null);
                restaurantCollectionRestaurant = em.merge(restaurantCollectionRestaurant);
            }
            em.remove(caterer);
            em.getTransaction().commit();
        } catch (Exception ex) {
            try {
            } catch (Exception re) {
                throw new RollbackFailureException("An error occurred attempting to roll back the transaction.", re);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Caterer> findCatererEntities() {
        return findCatererEntities(true, -1, -1);
    }

    public List<Caterer> findCatererEntities(int maxResults, int firstResult) {
        return findCatererEntities(false, maxResults, firstResult);
    }

    private List<Caterer> findCatererEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Caterer.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Caterer findCaterer(Integer id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Caterer.class, id);

        } finally {
            em.close();
        }
    }

    public int findUId(String uID) {
        try {
            List<Caterer> lstC = this.findCatererEntities();
            boolean flag = true;
            for (Caterer ct : lstC) {
                if (ct.getUserId().equals(uID)) {
                    flag = false;
                }
            }
            if (flag == false) {
                return 1;
            } else {
                return 0;
            }
        } catch (Exception e) {
            System.out.println("ex find IUD" + e.getMessage());
            return 0;
        }
    }

    public int getCatererCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Caterer> rt = cq.from(Caterer.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }
}
